1. /* sifbdfct.cpp by K.Tsuru */
  2. // function ID = 4106 BRADIX
  3. /********************************************************************
  4. SInteger class
  5. It provides the factorial n! using the partial products.
  6. It is a few times faster than BFact(), because the FFT multiplication
  7. can be used.
  8. *********************************************************************/
  9. #ifndef SN_H
  10. #include "sn.h"
  11. #endif
  12. /*********************************************************************
  13. sub-function
  14. It provides a product of continuous integers begining with f(<=m).
  15. r = f(f+1)....g
  16. If the processing ended(g==m) it returns zero, else "g+1" i.e. the
  17. next integer.
  18. **********************************************************************/
  19. static ulong MultContNum(ulong f, ulong m, uint fig, SInteger& r){
  20. r.SetLong(f);
  21. if(f == m) return 0;
  22. ulong i = f+1;
  23. int end = 0;
  24. while((r.Head() < fig) && !end){
  25. IsMult(r, i, r);
  26. if(i == m) end = 1;
  27. i++;
  28. }
  29. return end ? 0 : i;
  30. }
  31. // SNBlock version n!
  32. SInteger BdFact(ulong n){
  33. long fig = long( (double)Stirling(n)/log10((double)BRADIX) ) +1;//the number of figures in BRADIX ver. 2.17
  34. if(fig >= (long)SNManager::SNMaxSize(SNManager::BIN_INT)){
  35. SNManager::SetError(SNManager::OUT_OF_RANGE, "BdFact", 4106);
  36. }
  37. SInteger m; // m = 1
  38. if(n < 2LU){ m.SetLong(1L); return m; }
  39. uint size_mul = 2u;//The speed depends on this value.
  40. uint size = size_mul*m.FFTMinSize(), s2 = uint(fig/(long)(size-2u));
  41. s2 = ceilpow2(s2+1u); //+1u considering s2 == 0
  42. SNBlock <SInteger> w(s2); // work area
  43. ulong i =2LU;
  44. // step 1 : It makes partial products whose figure is "size" or lower.
  45. uint s, k = 0;
  46. while(i && (k < s2)){
  47. w[k].FigureAlloc(size, 0);
  48. i = MultContNum(i, n, size-2u, w[k++]);
  49. }
  50. if( (i == 0) && (k == 1u) ) return w[0];
  51. for(;k < s2; k++) w[k].SetSmall(1);//It fills the residual part of w[] with one.
  52. // step 2 : It composes the partial products.
  53. s = s2;
  54. while(s >= 2u){
  55. for(k = 0; k <= s-2u; k += 2u){
  56. //When w[k] == 1, w[k+1] == 1.
  57. if(w[k].IsOne() && w[k+1u].IsOne()) w[k/2u].SetSmall(1);
  58. else if(w[k+1].IsOne()) w[k/2u] = w[k];
  59. else w[k/2u] = w[k+1u]*w[k]; //The FFT multiplication is used.
  60. }
  61. s /= 2u;
  62. //It frees the memory.
  63. for(k = s; k < 2u*s; k++) w[k].SizeZero();
  64. }
  65. while(i){ //recidual part exists? perhaps not
  66. i = MultContNum(i, n, size-2u, m);
  67. w[0] *= m;
  68. }
  69. return w[0]; // SNBlock class's destructor frees the memory.
  70. }

sifbdfct.cpp : last modifiled at 2014/05/08 16:23:18(2,486 bytes)
created at 2016/04/25 14:53:17
The creation time of this html file is 2017/10/25 11:09:45 (Wed Oct 25 11:09:45 2017).